/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2005
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.ui.rich.full.command;

import java.util.ArrayList;
import java.util.ListIterator;

import javax.swing.JInternalFrame;

import br.ufmg.dees.insane.commons.command.Command;
import br.ufmg.dees.insane.commons.controller.Controller;
import br.ufmg.dees.insane.commons.dialogs.TabbedDialog;
import br.ufmg.dees.insane.commons.view.DrawingArea;
import br.ufmg.dees.insane.model.disc.element.Element;
import br.ufmg.dees.insane.model.disc.element.FrameElement;
import br.ufmg.dees.insane.model.disc.element.ParametricElement;
import br.ufmg.dees.insane.model.disc.element.force.ElementForce;
import br.ufmg.dees.insane.model.disc.element.force.ElementSide;
import br.ufmg.dees.insane.model.disc.element.force.Side;
import br.ufmg.dees.insane.model.disc.node.Node;
import br.ufmg.dees.insane.model.disc.pointforce.PointForce;
import br.ufmg.dees.insane.ui.rich.full.InsaneInternalInterface;
import br.ufmg.dees.insane.ui.rich.full.dialogs.ElmDistForcesDialog;
import br.ufmg.dees.insane.ui.rich.full.dialogs.LineForcesDialog;

/**
 *
 * @author Fonseca, Flavio & Pitangueira, Roque
 * @since April 2004
 */
public class SetElmDistForcesCommand implements Command, Cloneable {
	
	private InsaneInternalInterface parent;
	private Controller controller;
	private DrawingArea da;
	private Side sd ;
	
//*****************************************************************************
	
	/** Creates new SetElmDistForcesCommand */
	public SetElmDistForcesCommand(JInternalFrame parent) {
		this.parent = (InsaneInternalInterface)parent;
		controller = this.parent.getController();
		da = this.parent.getDrawing();
	}
	
//*****************************************************************************
	
	/** Execute method. */
	public void execute() {
		
		boolean changed = false;
		
		ArrayList elms = controller.getSelection();
		if ( elms.size() < 1 ) {
			controller.selectAll();
			elms = controller.getSelection();
		}
		
		if (elms.size() == 0) {
			parent.addOutputText("There is no elements in model.");
			return;
		}
		
		//SurfaceForcesDialog dlgParametric;
		LineForcesDialog dlgParametric;
		ElmDistForcesDialog dlg;
		
		ListIterator elements = elms.listIterator();
		while(elements.hasNext()) {
			Element elm = (Element)elements.next();
			
			if (elm instanceof ParametricElement){
				ElementSide elmSide = new ElementSide((ParametricElement)elm);
				elmSide.mountSide();
				ArrayList sides = elmSide.getSidesList();
				
				sd= (Side)sides.get(0);
				
				    //dlgParametric = new SurfaceForcesDialog(parent, (ParametricElement)elm);
				    dlgParametric = new LineForcesDialog(parent, (ParametricElement)elm);
				    int retVal = dlgParametric.showDialog();
				    if (retVal == TabbedDialog.OK_OPTION){
				    
				    	
						//int nRow = ((ParametricElement)elm).getIncidence().size();
						int nRow = elmSide.getNumberOfSides();
						
						if ( ((ParametricElement)elm).getType(1)=='L' ) {
							if ( ((ParametricElement)elm).getType(0)=='T' ) {
							nRow = (int)(((Math.sqrt(1+8*nRow)-1)/2)-1)*3;
							} else {
								nRow = (int)(Math.sqrt(nRow)-1)*4;
							}
						}
						String[][] sForces = dlgParametric.getLineForce();
						int lb = 0;
						int lb2 = 0;
						int last = 0;
						
						if (sd.getNNodes()==2){
							
						
							Node n1= new Node();
							Node n2= new Node();
							
							//ArrayList nodesSides = dlgParametric.getNodesSides();	
							
							for (int count = (nRow - 1); count >= 0; count--) {
						    //for (int count = 0; count < nRow-1; count++) {
								double Fxi = 0;
								double Fyi = 0;
								double Mzi = 0;
								double Fxf = 0;
								double Fyf = 0;
								double Mzf = 0;
								
								if ( sForces[count][1] != null && sForces[count][1] != "" )
									Fxi = Double.parseDouble( sForces[count][1] );
								if ( sForces[count][2] != null && sForces[count][2] != "" )
									Fyi = Double.parseDouble( sForces[count][2] );
								if ( sForces[count][3] != null && sForces[count][3] != "" )
									Mzi = Double.parseDouble( sForces[count][3] );
								if ( sForces[count][4] != null && sForces[count][4] != "" )
									Fxf = Double.parseDouble( sForces[count][4] );
								if ( sForces[count][5] != null && sForces[count][5] != "" )
									Fyf = Double.parseDouble( sForces[count][5] );
								if ( sForces[count][6] != null && sForces[count][6] != "" )
									Mzf = Double.parseDouble( sForces[count][6] );
								
								
								if ( Fxi!=0 || Fyi!=0 || Mzi!=0 || Fxf!=0 || Fyf!=0 || Mzf!=0 ) {
								//if ( Fxi!=0 || Fyi!=0 || Mzi!=0) {
									
									lb++;
									
									n1 = (Node)((ParametricElement)elm).getIncidence().get(count);
									n2 = (Node)((ParametricElement)elm).getIncidence().get(last);
									
									//n1 = (Node)(nodesSides).get(count);
									//n2 = (Node)(nodesSides).get(count+1);
										
									
									PointForce p1 = new PointForce();
									p1.setLabel("" + ((ParametricElement)elm).getLabel() + ".pf" + lb );
									p1.setCoord( n1.getCoord() );
									p1.setForce(0, Fxi);
									p1.setForce(1, Fyi);
									p1.setForce(5, Mzi);
									//n1.setPointForce(p1);
									PointForce p2 = new PointForce();
									lb++;
									p2.setLabel("" + ((ParametricElement)elm).getLabel() + ".pf" + lb);
									p2.setCoord( n2.getCoord() );
									p2.setForce(0, Fxf);
									p2.setForce(1, Fyf);
									p2.setForce(5, Mzf);
									//pointForces.add(p1);
									ElementForce e1 = new ElementForce();
									lb2++;
									e1.setLabel("" + ((ParametricElement)elm).getLabel() + ".ef" + lb2);
									e1.add(p1);
									e1.add(p2);
									
									((ParametricElement)elm).addElmLineForce(e1);
								}
								last = count;
								
							}
						   
					}
						if (sd.getNNodes()==3){
							
							
							Node n1= new Node();
							Node n2= new Node();
							Node n3= new Node();
							int cont = ((ParametricElement)elm).getIncidence().size()-2;
							
							for (int count = (nRow - 1); count >= 0; count--) {
						    //for (int count = 0; count < nRow-2; count++) {
								double Fxi = 0;
								double Fyi = 0;
								double Mzi = 0;
								double Fxf = 0;
								double Fyf = 0;
								double Mzf = 0;
								
								if ( sForces[count][1] != null && sForces[count][1] != "" )
									Fxi = Double.parseDouble( sForces[count][1] );
								if ( sForces[count][2] != null && sForces[count][2] != "" )
									Fyi = Double.parseDouble( sForces[count][2] );
								if ( sForces[count][3] != null && sForces[count][3] != "" )
									Mzi = Double.parseDouble( sForces[count][3] );
								if ( sForces[count][4] != null && sForces[count][4] != "" )
									Fxf = Double.parseDouble( sForces[count][4] );
								if ( sForces[count][5] != null && sForces[count][5] != "" )
									Fyf = Double.parseDouble( sForces[count][5] );
								if ( sForces[count][6] != null && sForces[count][6] != "" )
									Mzf = Double.parseDouble( sForces[count][6] );
								
								if ( Fxi!=0 || Fyi!=0 || Mzi!=0 || Fxf!=0 || Fyf!=0 || Mzf!=0 ) {
								//if ( Fxi!=0 || Fyi!=0 || Mzi!=0) {
									
									lb++;
									
									n1 = (Node)((ParametricElement)elm).getIncidence().get(cont);
									n2 = (Node)((ParametricElement)elm).getIncidence().get(cont+1);
									n3 = (Node)((ParametricElement)elm).getIncidence().get(last);
									
									PointForce p1 = new PointForce();
									p1.setLabel("" + ((ParametricElement)elm).getLabel() + ".pf" + lb );
									p1.setCoord( n1.getCoord() );
									p1.setForce(0, Fxi);
									p1.setForce(1, Fyi);
									p1.setForce(5, Mzi);
									//n1.setPointForce(p1);
									PointForce p2 = new PointForce();
									lb++;
									p2.setLabel("" + ((ParametricElement)elm).getLabel() + ".pf" + lb);
									p2.setCoord( n2.getCoord() );
									p2.setForce(0, ((Fxi+Fxf)/2));
									p2.setForce(1, ((Fyi+Fyf)/2));
									p2.setForce(5, ((Mzi+Mzf)/2));
									PointForce p3 = new PointForce();
									lb++;
									p3.setLabel("" + ((ParametricElement)elm).getLabel() + ".pf" + lb);
									p3.setCoord( n3.getCoord() );
									p3.setForce(0, Fxf);
									p3.setForce(1, Fyf);
									p3.setForce(5, Mzf);
									//pointForces.add(p1);
									ElementForce e1 = new ElementForce();
									lb2++;
									e1.setLabel("" + ((ParametricElement)elm).getLabel() + ".ef" + lb2);
									e1.add(p1);
									e1.add(p2);
									e1.add(p3);
									
									((ParametricElement)elm).addElmLineForce(e1);
								}
								last = cont;
								cont--;
								cont--;
								
							}
						   
						}  
						
						if (sd.getNNodes()==4){
							
							
							Node n1= new Node();
							Node n2= new Node();
							Node n3= new Node();
							Node n4= new Node();
							int cont = ((ParametricElement)elm).getIncidence().size()-3;
							
							for (int count = (nRow - 1); count >= 0; count--) {
						    //for (int count = 0; count < nRow-3; count++) {
								double Fxi = 0;
								double Fyi = 0;
								double Mzi = 0;
								double Fxf = 0;
								double Fyf = 0;
								double Mzf = 0;
								
								if ( sForces[count][1] != null && sForces[count][1] != "" )
									Fxi = Double.parseDouble( sForces[count][1] );
								if ( sForces[count][2] != null && sForces[count][2] != "" )
									Fyi = Double.parseDouble( sForces[count][2] );
								if ( sForces[count][3] != null && sForces[count][3] != "" )
									Mzi = Double.parseDouble( sForces[count][3] );
								if ( sForces[count][4] != null && sForces[count][4] != "" )
									Fxf = Double.parseDouble( sForces[count][4] );
								if ( sForces[count][5] != null && sForces[count][5] != "" )
									Fyf = Double.parseDouble( sForces[count][5] );
								if ( sForces[count][6] != null && sForces[count][6] != "" )
									Mzf = Double.parseDouble( sForces[count][6] );
								
								if ( Fxi!=0 || Fyi!=0 || Mzi!=0 || Fxf!=0 || Fyf!=0 || Mzf!=0 ) {
								//if ( Fxi!=0 || Fyi!=0 || Mzi!=0) {
									
									lb++;
									
									n1 = (Node)((ParametricElement)elm).getIncidence().get(cont);
									n2 = (Node)((ParametricElement)elm).getIncidence().get(cont+1);
									n3 = (Node)((ParametricElement)elm).getIncidence().get(cont+2);
									n4 = (Node)((ParametricElement)elm).getIncidence().get(last);
									
									
									PointForce p1 = new PointForce();
									p1.setLabel("" + ((ParametricElement)elm).getLabel() + ".pf" + lb );
									p1.setCoord( n1.getCoord() );
									p1.setForce(0, Fxi);
									p1.setForce(1, Fyi);
									p1.setForce(5, Mzi);
									//n1.setPointForce(p1);
									PointForce p2 = new PointForce();
									lb++;
									p2.setLabel("" + ((ParametricElement)elm).getLabel() + ".pf" + lb);
									p2.setCoord( n2.getCoord() );
									p2.setForce(0, ((Fxi)-((Fxi-Fxf)*1/3)));
									p2.setForce(1, ((Fyi)-((Fyi-Fyf)*1/3)));
									p2.setForce(5, ((Mzi)-((Mzi-Mzf)*1/3)));
									PointForce p3 = new PointForce();
									lb++;
									p3.setLabel("" + ((ParametricElement)elm).getLabel() + ".pf" + lb);
									p2.setCoord( n3.getCoord() );
									p3.setForce(0, ((Fxi)-((Fxi-Fxf)*2/3)));
									p3.setForce(1, ((Fyi)-((Fyi-Fyf)*2/3)));
									p3.setForce(5, ((Mzi)-((Mzi-Mzf)*2/3)));
									PointForce p4 = new PointForce();
									lb++;
									p4.setLabel("" + ((ParametricElement)elm).getLabel() + ".pf" + lb);
									p4.setCoord( n4.getCoord() );
									p4.setForce(0, Fxf);
									p4.setForce(1, Fyf);
									p4.setForce(5, Mzf);
									//pointForces.add(p1);
									ElementForce e1 = new ElementForce();
									lb2++;
									e1.setLabel("" + ((ParametricElement)elm).getLabel() + ".ef" + lb2);
									e1.add(p1);
									e1.add(p2);
									e1.add(p3);
									e1.add(p4);
									
									((ParametricElement)elm).addElmLineForce(e1);
								}
								last = cont;
								cont--;
								cont--;
							}
						   
						}  
//					  
					    
						parent.setMessage("Adding Line Force");
					}
				    
				    
			}
			if (elm instanceof FrameElement){
				dlg = new ElmDistForcesDialog(parent);
		        int retVal = dlg.showDialog();
		        if (retVal == TabbedDialog.OK_OPTION){
					
					//ListIterator elements = elms.listIterator();
					//while(elements.hasNext()) {
						
						//FrameElement elm = (FrameElement)elements.next();
						
						if (elm.getElmLineForcesList().size() != dlg.distForces.size()) {
							changed = true;
						} else {
							ListIterator dfs1 = elm.getElmLineForcesList().listIterator();
							ListIterator dfs2 = dlg.distForces.listIterator();
							while (dfs1.hasNext()) {
								ElementForce df1 = (ElementForce)dfs1.next();
								ElementForce df2 = (ElementForce)dfs2.next();
								PointForce cf1a = (PointForce)df1.getPointForcesList().get(0);
								PointForce cf1b = (PointForce)df1.getPointForcesList().get(1);
								PointForce cf2a = (PointForce)df2.getPointForcesList().get(0);
								PointForce cf2b = (PointForce)df2.getPointForcesList().get(1);
								
								if (cf1a.getCoord().x != cf2a.getCoord().x)
									changed = true;
								if (cf1a.getForce(0) != cf2a.getForce(0))
									changed = true;
								if (cf1a.getForce(1) != cf2a.getForce(1))
									changed = true;
								if (cf1a.getForce(2) != cf2a.getForce(2))
									changed = true;
								if (cf1a.getForce(3) != cf2a.getForce(3))
									changed = true;
								if (cf1a.getForce(4) != cf2a.getForce(4))
									changed = true;
								if (cf1a.getForce(5) != cf2a.getForce(5))
									changed = true;
								
								if (cf1b.getCoord().x != cf2b.getCoord().x)
									changed = true;
								if (cf1b.getForce(0) != cf2b.getForce(0))
									changed = true;
								if (cf1b.getForce(1) != cf2b.getForce(1))
									changed = true;
								if (cf1b.getForce(2) != cf2b.getForce(2))
									changed = true;
								if (cf1b.getForce(3) != cf2b.getForce(3))
									changed = true;
								if (cf1b.getForce(4) != cf2b.getForce(4))
									changed = true;
								if (cf1b.getForce(5) != cf2b.getForce(5))
									changed = true;
							}
						}
						
						//Setting ElmLineForcesList
						ArrayList<ElementForce> dforces = new ArrayList<ElementForce>();
						ListIterator dfs = dlg.distForces.listIterator();
						while (dfs.hasNext()) {
							
							ElementForce ef = (ElementForce)dfs.next();
							PointForce pf1 = (PointForce)ef.getPointForcesList().get(0);
							PointForce pf2 = (PointForce)ef.getPointForcesList().get(1);
							ElementForce ef2 = new ElementForce();
							PointForce pf1a = new PointForce();
							PointForce pf2a = new PointForce();
							
							if (pf1.getCoord().x > ((FrameElement) elm).getLength()){
								pf1a.getCoord().x = ((FrameElement) elm).getLength();
							} else {
								pf1a.setCoord(pf1.getCoord().x, 0, 0);
							}
							pf1a.setForce(0, pf1.getForce(0));
							pf1a.setForce(1, pf1.getForce(1));
							pf1a.setForce(2, pf1.getForce(2));
							pf1a.setForce(3, pf1.getForce(3));
							pf1a.setForce(4, pf1.getForce(4));
							pf1a.setForce(5, pf1.getForce(5));
							ef2.getPointForcesList().add(0, pf1a);
							
							if (pf2.getCoord().x > ((FrameElement) elm).getLength()){
								pf2a.getCoord().x = ((FrameElement) elm).getLength();
							} else {
								pf2a.setCoord(pf2.getCoord().x, 0, 0);
							}
							pf2a.setForce(0, pf2.getForce(0));
							pf2a.setForce(1, pf2.getForce(1));
							pf2a.setForce(2, pf2.getForce(2));
							pf2a.setForce(3, pf2.getForce(3));
							pf2a.setForce(4, pf2.getForce(4));
							pf2a.setForce(5, pf2.getForce(5));
							ef2.getPointForcesList().add(1, pf2a);
							
							if (pf1a.getCoord().x==0 && pf2a.getCoord().x==0) {
								pf2a.getCoord().x = ((FrameElement) elm).getLength();
							}
							
							dforces.add(ef2);
							
						}
						elm.setElmLineForcesList(dforces);
						
				
					
				}
				
				
			}
		   
		}
		
		
		//parent.addToUndo((Command)this.clone());
		controller.unSelectAll();
		controller.compose();
		da.repaint();
		
		if (changed)
			parent.cleanResults();
		
	}
	
//*****************************************************************************
	
	/** Impossible to undo - not implemented. */
	public void undo() {
	}
	
//*****************************************************************************
	
	/** Impossible to redo - not implemented. */
	public void redo() {
	}
	
//*****************************************************************************
	
	/** Clone method. */
	public Object clone() {
		try {
			SetElmDistForcesCommand cmd = (SetElmDistForcesCommand)super.clone();
			return cmd;
		}catch (CloneNotSupportedException e) {
			throw new Error("Clonning ERROR - This should never happen!");
		}
	}
	
//*****************************************************************************
}

